package jp.ac.kobe_u.cs.cream;

import jp.ac.kobe_u.cs.cream.*;
import java.util.*;

public class IntComparison extends Constraint {
    public static final int LE = 0;
    public static final int LT = 1;
    public static final int GE = 2;
    public static final int GT = 3;
    private int comparison;
    private Variable v[];

    public IntComparison(Network net, int comp, Variable v0, Variable v1) {
	this(net, comp, new Variable[] {v0, v1});
    }

    public IntComparison(Network net, int comp, Variable v0, int x1) {
	this(net, comp, v0, new IntVariable(net, x1));
    }

    public IntComparison(Network net, int comp, int x0, Variable v1) {
	this(net, comp, new IntVariable(net, x0), v1);
    }

    private IntComparison(Network net, int comp, Variable v[]) {
	super(net);
	comparison = comp;
	this.v = v;
    }

    protected Constraint copy(Network net) {
	return new IntComparison(net, comparison, Constraint.copy(this.v, net));
    }

    protected boolean isModified() {
	return isModified(v);
    }

    private boolean satisfyLE(Variable v0, Variable v1, Trail trail) {
	IntDomain d0 = (IntDomain)v0.getDomain();
	IntDomain d1 = (IntDomain)v1.getDomain();
	d0 = d0.capInterval(IntDomain.MIN_VALUE, d1.max());
	if (d0.isEmpty())
	    return false;
	v0.updateDomain(d0, trail);
	d1 = d1.capInterval(d0.min(), IntDomain.MAX_VALUE);
	if (d1.isEmpty())
	    return false;
	v1.updateDomain(d1, trail);
	return true;
    }

    private boolean satisfyLT(Variable v0, Variable v1, Trail trail) {
	IntDomain d0 = (IntDomain)v0.getDomain();
	IntDomain d1 = (IntDomain)v1.getDomain();
	d0 = d0.capInterval(IntDomain.MIN_VALUE, d1.max()-1);
	if (d0.isEmpty())
	    return false;
	v0.updateDomain(d0, trail);
	d1 = d1.capInterval(d0.min()+1, IntDomain.MAX_VALUE);
	if (d1.isEmpty())
	    return false;
	v1.updateDomain(d1, trail);
	return true;
    }

    protected boolean satisfy(Trail trail) {
	switch (comparison) {
	case LE:
	    return satisfyLE(v[0], v[1], trail);
	case LT:
	    return satisfyLT(v[0], v[1], trail);
	case GE:
	    return satisfyLE(v[1], v[0], trail);
	case GT:
	    return satisfyLT(v[1], v[0], trail);
	}
	return false;
    }

    public String toString() {
	String c = "";
	switch (comparison) {
	case LE:
	    c = "LE"; break;
	case LT:
	    c = "LT"; break;
	case GE:
	    c = "GE"; break;
	case GT:
	    c = "GT"; break;
	}
	return "IntComparison(" + c + "," + Constraint.toString(v) + ")";
    }
}
